/***************************************************************************
 *   KShootout - online shootout card game.                                *
 *   Copyright (C) 2008, 2009  MacJariel                                   *
 *                                                                         *
 *   KShootout is free software: you can redistribute it and/or modify     *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation, either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   KShootout is distributed in the hope that it will be useful,          *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with KShootout.  If not, see <http://www.gnu.org/licenses/>.    *
 ***************************************************************************/
#include "servereventparser.h"
#include "gamestructparser.h"
#include "stringconverter.h"
#include "util.h"

/*[[[cog
import cog
from servereventdefs import *
]]]
[[[end]]]*/

/* static */
void ServerEventParser::write(QXmlStreamWriter* w, ServerEventDataPtr e)
{
    w->writeStartElement("server-event");
    switch (e->t()) {
    /*[[[cog
    for se in ServerEvents:
        cog.outl("case ServerEventData::%(serverEventType)s: write(w, e.staticCast<%(structName)s>());" % se)
        cog.outl("    break;")
    ]]]*/
    case ServerEventData::EnterGameType: write(w, e.staticCast<EnterGameEventData>());
        break;
    case ServerEventData::ExitGameType: write(w, e.staticCast<ExitGameEventData>());
        break;
    case ServerEventData::CreatePlayerType: write(w, e.staticCast<CreatePlayerEventData>());
        break;
    case ServerEventData::RemovePlayerType: write(w, e.staticCast<RemovePlayerEventData>());
        break;
    case ServerEventData::ChatMessageType: write(w, e.staticCast<ChatMessageEventData>());
        break;
    case ServerEventData::GameUpdateType: write(w, e.staticCast<GameUpdateEventData>());
        break;
    //[[[end]]]
    }
    w->writeEndElement();
}

/* static */
ServerEventDataPtr ServerEventParser::read(XmlNode* node)
{
    if (node->name() != "server-event" || node->getFirstChild() == 0) {
        return ServerEventDataPtr();
    }
    node = node->getFirstChild();
    /*[[[cog
    for se in ServerEvents:
        cog.outl("if (node->name() == %(elemName)s) {" % se)
        cog.outl("    return read%(serverEventName)s(node);" % se)
        cog.outl("}")
    ]]]*/
    if (node->name() == "enter-game") {
        return readEnterGame(node);
    }
    if (node->name() == "exit-game") {
        return readExitGame(node);
    }
    if (node->name() == "create-player") {
        return readCreatePlayer(node);
    }
    if (node->name() == "remove-player") {
        return readRemovePlayer(node);
    }
    if (node->name() == "chat-message") {
        return readChatMessage(node);
    }
    if (node->name() == "game-update") {
        return readGameUpdate(node);
    }
    //[[[end]]]
    return ServerEventDataPtr();
}

/*[[[cog
for se in ServerEvents:
    cog.outl("void ServerEventParser::write%(serverEventName)s(QXmlStreamWriter* w, const %(structName)sPtr& se)" % se)
    cog.outl(se.genWriter("w", "se", True))
    cog.outl("%(structName)sPtr ServerEventParser::read%(serverEventName)s(XmlNode* n)" % se)
    cog.outl(se.genReader("n", None, True))
    cog.outl();
]]]*/
void ServerEventParser::writeEnterGame(QXmlStreamWriter* w, const EnterGameEventDataPtr& se)
{
    w->writeStartElement("enter-game");
    w->writeAttribute("actor-id", toString(se->actorId));
    GameStructParser::write(w, se->gameSyncData, "game-sync");
    w->writeEndElement();
}

EnterGameEventDataPtr ServerEventParser::readEnterGame(XmlNode* n)
{
    EnterGameEventDataPtr res(new EnterGameEventData());
    fromString(n->attribute("actor-id"), res->actorId);
    foreach (XmlNode* ch, n->getChildren()) {
        if (ch->name() == "game-sync") {
            
            GameStructParser::read(ch, res->gameSyncData);
            continue;
        }
    }
    return res;
}

void ServerEventParser::writeExitGame(QXmlStreamWriter* w, const ExitGameEventDataPtr& se)
{
    w->writeStartElement("exit-game");
    w->writeAttribute("game-id", toString(se->gameId));
    w->writeEndElement();
}

ExitGameEventDataPtr ServerEventParser::readExitGame(XmlNode* n)
{
    ExitGameEventDataPtr res(new ExitGameEventData());
    fromString(n->attribute("game-id"), res->gameId);
    return res;
}

void ServerEventParser::writeCreatePlayer(QXmlStreamWriter* w, const CreatePlayerEventDataPtr& se)
{
    w->writeStartElement("create-player");
    w->writeAttribute("game-id", toString(se->gameId));
    GameStructParser::write(w, se->playerData, "player");
    w->writeEndElement();
}

CreatePlayerEventDataPtr ServerEventParser::readCreatePlayer(XmlNode* n)
{
    CreatePlayerEventDataPtr res(new CreatePlayerEventData());
    fromString(n->attribute("game-id"), res->gameId);
    foreach (XmlNode* ch, n->getChildren()) {
        if (ch->name() == "player") {
            
            GameStructParser::read(ch, res->playerData);
            continue;
        }
    }
    return res;
}

void ServerEventParser::writeRemovePlayer(QXmlStreamWriter* w, const RemovePlayerEventDataPtr& se)
{
    w->writeStartElement("remove-player");
    w->writeAttribute("game-id", toString(se->gameId));
    w->writeAttribute("player-id", toString(se->playerId));
    w->writeEndElement();
}

RemovePlayerEventDataPtr ServerEventParser::readRemovePlayer(XmlNode* n)
{
    RemovePlayerEventDataPtr res(new RemovePlayerEventData());
    fromString(n->attribute("game-id"), res->gameId);
    fromString(n->attribute("player-id"), res->playerId);
    return res;
}

void ServerEventParser::writeChatMessage(QXmlStreamWriter* w, const ChatMessageEventDataPtr& se)
{
    w->writeStartElement("chat-message");
    w->writeAttribute("game-id", toString(se->gameId));
    w->writeAttribute("client-id", toString(se->clientId));
    w->writeAttribute("player-id", toString(se->playerId));
    w->writeAttribute("sender-name", toString(se->senderName));
    w->writeAttribute("text", toString(se->text));
    w->writeEndElement();
}

ChatMessageEventDataPtr ServerEventParser::readChatMessage(XmlNode* n)
{
    ChatMessageEventDataPtr res(new ChatMessageEventData());
    fromString(n->attribute("game-id"), res->gameId);
    fromString(n->attribute("client-id"), res->clientId);
    fromString(n->attribute("player-id"), res->playerId);
    fromString(n->attribute("sender-name"), res->senderName);
    fromString(n->attribute("text"), res->text);
    return res;
}

void ServerEventParser::writeGameUpdate(QXmlStreamWriter* w, const GameUpdateEventDataPtr& se)
{
    w->writeStartElement("game-update");
    w->writeAttribute("game-id", toString(se->gameId));
    if (se->hasFlag(GameUpdateEventData::IsStartableAttr)) {
         w->writeAttribute("is-startable", toString(se->isStartable));
    }
    w->writeEndElement();
}

GameUpdateEventDataPtr ServerEventParser::readGameUpdate(XmlNode* n)
{
    GameUpdateEventDataPtr res(new GameUpdateEventData());
    fromString(n->attribute("game-id"), res->gameId);
    if (n->hasAttribute("is-startable")) {
        res->setFlag(GameUpdateEventData::IsStartableAttr);
        fromString(n->attribute("is-startable"), res->isStartable);
    }
    return res;
}

//[[[end]]]